package fr.sportsurbains;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.jsoup.HttpStatusException;

import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.FragmentTransaction;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.SimpleAdapter;
import android.widget.SimpleAdapter.ViewBinder;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gcm.GCMRegistrar;

import fr.sportsurbains.reader.TopicsReader;
import fr.sportsurbains.tools.BitmapManager;
import fr.sportsurbains.tools.DBManager;

@SuppressLint("HandlerLeak")
public class MainActivity extends FragmentActivity implements
		ActionBar.TabListener {

	public static final String HOMEPAGE = "http://www.sportsurbains.com/";
	public static final String[] CATEGORIES = {"info-en-continu","video","bike-polo","breakdance","parkour","capoeira","tricks",
		"skate","roller","bmx","street-jam","street-word","echasses-urbains","golf-urbain","freestyle-foot","street-surfing",
		"street-tennis","monocyle-street","double-dutch","slackline","basket-2-rue","foot-2-rue","insolite"};
	public static final int DEFAULT_TOPICS_NUMBER = 16;

	private static ExecutorService loadThread = Executors.newFixedThreadPool(5); ;
	MyPagerAdapter mPagerAdapter;

	/**
	 * The {@link ViewPager} that will host the section contents.
	 */
	ViewPager mViewPager;
	BitmapManager bmpManager;
	ProgressDialog progressDialog;
	Handler refreshHandler;
	Handler initHandler;
	Handler loadHandler;
	Handler welcomeHandler;
	DBManager dbmanager;
	AsyncTask<Void, Void, Void> mRegisterTask;
	List<List<Map<String,String>>> categories;
	List<BaseAdapter> adapters;
	List<ListView> listviews;
	List<View> views;
	SharedPreferences settings;
	private boolean timeout = false;
	
	TopicsReader tr;
	ListView lv;
	ViewBinder vb = new ViewBinder() {

		@Override
		public boolean setViewValue(  
                View view,   
                Object data,    
             String textRepresentation) {    
	        if(view instanceof ImageView  && data instanceof String){ 
	            ImageView iv = (ImageView) view;    
	            bmpManager.loadBitmap((String)data, iv);
	            return true;    
	        }else if(view.getId() == R.id.topic) {
	        	view.setTag(data);
	        	return true;
	        }else    return false;    
		}
	};

	@SuppressLint("HandlerLeak")
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//setContentView(R.layout.activity_main);
		setContentView(R.layout.welcome);  
		getActionBar().hide();
        welcomeHandler = new Handler()  
        {  
                 @Override  
                 public void handleMessage(Message msg)  
                 {  
                     if(msg.what == 1) // handler接收到相关的消息后  
                          {  
	                         setContentView(R.layout.activity_main);// 显示真正的应用界面  
	                         initMainView();
                          }  
                 }  
        };  
        
        new Thread() {
			@Override
			public void run() {
				try {
					tr = new TopicsReader(HOMEPAGE);
				} catch (IOException e) {
					tr = null;
					if(e instanceof SocketTimeoutException) {
						timeout = true;
					} else if(e instanceof HttpStatusException) {
						Log.v("TEST","code status: "+((HttpStatusException)e).getStatusCode());
						Log.v("TEST","httpstatus : "+((HttpStatusException)e).toString());
					}
					e.printStackTrace();
				}
				welcomeHandler.sendEmptyMessage(1);
			}
		}.start();
		
	}
	
	public void initMainView() {

		settings = PreferenceManager.getDefaultSharedPreferences(this);
		String notif_key = getString(R.string.notif_key);
		boolean notif_enabled = settings.getBoolean(notif_key, false);
		if(notif_enabled) {
			enableNotification();
		}
		
		dbmanager = new DBManager(this);
		bmpManager = new BitmapManager(BitmapFactory.decodeResource(getResources(), R.drawable.loading17), dbmanager);

		progressDialog = new ProgressDialog(MainActivity.this);
		progressDialog.setTitle(getResources().getString(R.string.progressdialog_title));
		progressDialog.setMessage(getResources().getString(R.string.progressdialog_message));
		refreshHandler = new Handler() {
			@Override
			public void handleMessage (Message msg) {
				switch(msg.what) {
				case 0: progressDialog.show();break;
				case 1: progressDialog.hide();
					int section_position = mViewPager.getCurrentItem();
					
					refreshListView(tr,section_position,false);
					break;
				}					
			}
		};
		
		loadHandler = new Handler() {
			@SuppressLint("HandlerLeak")
			@Override
			public void handleMessage (Message msg) {
				switch(msg.what) {
				case 0: progressDialog.show();break;
				case 1: progressDialog.hide();
					int section_position = mViewPager.getCurrentItem();
					
					refreshListView(tr,section_position,true);
					break;
				}					
			}
		};
		
		initHandler = new Handler() {
			@Override
			public void handleMessage (Message msg) {
				for(int i = 0;i < CATEGORIES.length; i++) {
					SimpleAdapter adp = new SimpleAdapter(views.get(i).getContext(),categories.get(i),R.layout.topic,new String[]{"link","title","image","summary"},
							new int[]{R.id.topic,R.id.topic_title,R.id.topic_picture,R.id.topic_summary});
					adp.setViewBinder(vb);
					int id = 0;
					
					id = R.id.section;
					ListView listview = (ListView) views.get(i).findViewById(id);
					listview.setAdapter(adp);
					listview.setOnItemClickListener(new MyOnItemClickListener());
					listview.setOnScrollListener(new MyOnScrollListener());
					adapters.add(adp);
				}
                refreshListView(tr,0,false);

			}
		};

		// Set up the action bar.
		final ActionBar actionBar = getActionBar();
		actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
		actionBar.setDisplayShowTitleEnabled(false);
		actionBar.show();


		// Create the adapter that will return a fragment for each of the three
		// primary sections of the app.

		views = new ArrayList<View>();
		for(int i = 0; i < CATEGORIES.length; i++) {
			View viewPager = LayoutInflater.from(this).inflate(R.layout.section, null);
			views.add(viewPager);
		}
		
		mPagerAdapter = new MyPagerAdapter(this,views);

		// Set up the ViewPager with the sections adapter.
		mViewPager = (ViewPager) findViewById(R.id.pager);
		mViewPager.setAdapter(mPagerAdapter);

		// When swiping between different sections, select the corresponding
		// tab. We can also use ActionBar.Tab#select() to do this if we have
		// a reference to the Tab.
		mViewPager
				.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
					

					@Override
					public void onPageSelected(int position) {
						actionBar.setSelectedNavigationItem(position);
					}
				});
		
		categories = new ArrayList<List<Map<String,String>>>();
		adapters = new ArrayList<BaseAdapter>();

		// For each of the sections in the app, add a tab to the action bar.
		for (int i = 0; i < mPagerAdapter.getCount(); i++) {
			// Create a tab with text corresponding to the page title defined by
			// the adapter. Also specify this Activity object, which implements
			// the TabListener interface, as the callback (listener) for when
			// this tab is selected.
			actionBar.addTab(actionBar.newTab()
					.setText(mPagerAdapter.getPageTitle(i))
					.setTabListener(this));
		}
		new Thread() {
			@Override
			public void run() {
				initListView();
				initHandler.sendEmptyMessage(0);
			}
		}.start();
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		this.dbmanager.closeDB();
	}
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch(item.getItemId()) {
		case R.id.action_refresh:
			new Thread() {
				@Override
				public void run() {
					refreshHandler.sendEmptyMessage(0);
						try {
							Log.v("TEST", getHomePage());
							tr = new TopicsReader(getHomePage());
						} catch (IOException e) {
							tr = null;
							if(e instanceof SocketTimeoutException) {
								timeout = true;
							} else if(e instanceof HttpStatusException) {
								Log.v("TEST","code status: "+((HttpStatusException)e).getStatusCode());
								Log.v("TEST","httpstatus : "+((HttpStatusException)e).toString());
							}
							e.printStackTrace();
						}
					refreshHandler.sendEmptyMessage(1);
				}
			}.start();break;
		case R.id.action_recommend_to_friend:
			Uri smsToUri = Uri.parse("smsto:");    
			Intent mIntent = new Intent( android.content.Intent.ACTION_SENDTO, smsToUri );  
			mIntent.putExtra("sms_body", getResources().getString(R.string.action_content_invite));  
			startActivity( mIntent );   
			break;
		case R.id.action_about:
			Intent aint = new Intent(MainActivity.this,AboutActivity.class);
			startActivity(aint);
			break;
		case R.id.action_search:
			Intent sint = new Intent(MainActivity.this,SearchActivity.class);
			startActivity(sint);
			break;
		case R.id.action_settings:
			Intent setint = new Intent(MainActivity.this,SettingsActivity.class);
			startActivityForResult(setint,0);
			break;
		case R.id.action_edit:
			Intent eint = new Intent(Intent.ACTION_VIEW,Uri.parse(MainActivity.HOMEPAGE+"reportage/"));
			startActivity(eint);
		}
		return false;
		
	}
	
	protected  void onActivityResult(int requestCode, int resultCode, Intent data) {  
		String notif_key = getString(R.string.notif_key);
		boolean notif_enabled = settings.getBoolean(notif_key, false);
		if(notif_enabled) {
			enableNotification();
		} else {
			disableNotification();
		}
    }  

	@Override
	public void onTabSelected(ActionBar.Tab tab,
			FragmentTransaction fragmentTransaction) {
		// When the given tab is selected, switch to the corresponding page in
		// the ViewPager.
			mViewPager.setCurrentItem(tab.getPosition());
			View v = views.get(tab.getPosition());
			ListView lv = (ListView) v.findViewById(R.id.section);
			if(lv.getCount()==0&&tab.getPosition()!=0) {
				
				final ProgressBar circleProgressBar = (ProgressBar)v.findViewById(R.id.circleProgressBarTop);
				circleProgressBar.setVisibility(View.VISIBLE);  
				final int position = tab.getPosition();
				final Handler load = new Handler() {
					@Override
					public void handleMessage (Message msg) {
						circleProgressBar.setVisibility(View.GONE);
						refreshListView((TopicsReader)msg.obj,position,false);
					}
				};
				loadThread.execute(new Runnable() {   
		            public void run() {  
		            	TopicsReader tpr=null;
						try {
							tpr = new TopicsReader(getHomePage(position));
						} catch (IOException e) {
							tpr = null;
							if(e instanceof SocketTimeoutException) {
								timeout = true;
							} else if(e instanceof HttpStatusException) {
								Log.v("TEST","code status: "+((HttpStatusException)e).getStatusCode());
								Log.v("TEST","httpstatus : "+((HttpStatusException)e).toString());
							}
							e.printStackTrace();
						}
		                Message message = Message.obtain();  
		                message.obj = tpr;  
		                load.sendMessage(message);  
		            }  
		        });  
			}
	}

	@Override
	public void onTabUnselected(ActionBar.Tab tab,
			FragmentTransaction fragmentTransaction) {
	}

	@Override
	public void onTabReselected(ActionBar.Tab tab,
			FragmentTransaction fragmentTransaction) {
	}
	
	public void initListView() {
		
		for(int i = 0; i < CATEGORIES.length; i++) {
			List<Map<String,String>> topics = new ArrayList<Map<String,String>>();
			categories.add(topics);
		}
	}
	
	public void refreshListView(TopicsReader tr, final int tabid, boolean option) {
		int id = 0;
		int time = 0;
		String table = null;
		
		id = R.id.section;
		time = R.id.updated_time;
		table = CATEGORIES[tabid];
		if(tr == null) {
			Log.v("TEST", "tr is null");
			if(timeout) {
				Log.v("TEST", "time out is true");
				Toast.makeText(this, R.string.timeout, Toast.LENGTH_SHORT).show();
				timeout = false;
			}
		} else {
			List<Map<String,String>> topics = new ArrayList<Map<String,String>>();
			if(table.equals("info-en-continu")) {
				topics.addAll(tr.getInfoEnContinu());
//				dbmanager.addInfoEnContinu(topics);
			} else if(table.equals("video")) {
				topics.addAll(tr.getVideos());
//				dbmanager.addVideos(topics);
			} else {
				topics.addAll(tr.getTopics());
//				dbmanager.addTopics(topics, table);	
			}
			if(option == false) {
				List<Map<String,String>> category = categories.get(tabid);
				category.clear();
				category.addAll(topics);
				ListView listview = (ListView) views.get(tabid).findViewById(id);
				listview.setTag(tr.getNextUrl());
				TextView tv = (TextView) views.get(tabid).findViewById(time);
				tv.setText(getString(R.string.updated)+" "+getTime());
				adapters.get(tabid).notifyDataSetChanged();
			} else {
				List<Map<String,String>> category = categories.get(tabid);
				category.addAll(topics);
				ListView listview = (ListView) views.get(tabid).findViewById(id);
				listview.setTag(tr.getNextUrl());
				TextView tv = (TextView) views.get(tabid).findViewById(time);
				tv.setText(getString(R.string.updated)+" "+getTime());
				adapters.get(tabid).notifyDataSetChanged();
			}
		}
	}
	
	public String getTime() {
		String time = "";
		Calendar c = Calendar.getInstance();
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH);
		int day = c.get(Calendar.DAY_OF_MONTH);
		int hour = c.get(Calendar.HOUR_OF_DAY);
        int minute = c.get(Calendar.MINUTE);
        time = hour+":"+minute+" "+day+"-"+month+"-"+year;
		return time;
	}
	
	public void disableNotification() {
		if (GCMRegistrar.isRegisteredOnServer(this)) {
			GCMRegistrar.unregister(this);
		}
	}
	
	public void enableNotification() {
		GCMRegistrar.checkDevice(this);  
        GCMRegistrar.checkManifest(this);  
        final String regId = GCMRegistrar.getRegistrationId(this);  
        if (regId.equals("")) {  
          GCMRegistrar.register(this, GCMIntentService.SENDERID);  
          Log.v("TEST", "new device:"+GCMRegistrar.isRegistered(this)+GCMRegistrar.getRegistrationId(this));  
        } else {  
        	if (GCMRegistrar.isRegisteredOnServer(this)) {
                // Skips registration.
            } else {
                // Try to register again, but not in the UI thread.
                // It's also necessary to cancel the thread onDestroy(),
                // hence the use of AsyncTask instead of a raw thread.
                final Context context = this;
                mRegisterTask = new AsyncTask<Void, Void, Void>() {

                    @Override
                    protected Void doInBackground(Void... params) {
                        boolean registered =
                                ServerUtilities.register(context, regId);
                        // At this point all attempts to register with the app
                        // server failed, so we need to unregister the device
                        // from GCM - the app will try to register again when
                        // it is restarted. Note that GCM will send an
                        // unregistered callback upon completion, but
                        // GCMIntentService.onUnregistered() will ignore it.
                        if (!registered) {
                            GCMRegistrar.unregister(context);
                        }
                        return null;
                    }

                    @Override
                    protected void onPostExecute(Void result) {
                        mRegisterTask = null;
                    }

                };
                mRegisterTask.execute(null, null, null);
            }
          Log.v("TEST", "Already registered:"+GCMRegistrar.getRegistrationId(this));  
        }  
	}
	
	public String getHomePage() {
		return getHomePage(mViewPager.getCurrentItem());
	}
	public String getHomePage(int page) {
		int section_position = page;
		String temp = null;
		if(section_position == 0) {
			temp = HOMEPAGE;
		} else if(section_position == 1) {
			temp = HOMEPAGE+"video";
		} else {
			temp = HOMEPAGE+"category/"+CATEGORIES[section_position];
		}
		return temp;
	}
	
	public class MyOnScrollListener implements OnScrollListener {
		private boolean isLast = false;


		@Override
		public void onScroll(AbsListView arg0, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
			if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0) {      
                isLast = true;   
            }      
		}

		@Override
		public void onScrollStateChanged(AbsListView view, int scrollState) {
			if (isLast && scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {      
                //加载元素      
				final String url = (String)view.getTag();
				if(url != null) {
					final int position = mViewPager.getCurrentItem();
					View v = views.get(position);
					final ProgressBar circleProgressBar = (ProgressBar)v.findViewById(R.id.circleProgressBarBottom);
					circleProgressBar.setVisibility(View.VISIBLE);  
					final Handler load = new Handler() {
						@Override
						public void handleMessage (Message msg) {
							circleProgressBar.setVisibility(View.GONE);
							refreshListView((TopicsReader)msg.obj,position,true);
						}
					};
					loadThread.execute(new Runnable() {   
			            public void run() {  
			            	TopicsReader tpr=null;
							try {
								tpr = new TopicsReader(url);
							} catch (IOException e) {
								tpr = null;
								if(e instanceof SocketTimeoutException) {
									timeout = true;
								} else if(e instanceof HttpStatusException) {
									Log.v("TEST","code status: "+((HttpStatusException)e).getStatusCode());
									Log.v("TEST","httpstatus : "+((HttpStatusException)e).toString());
								}
								e.printStackTrace();
							}
			                Message message = Message.obtain();  
			                message.obj = tpr;  
			                load.sendMessage(message);  
			            }  
			        });  
					
	             
	                isLast = false;      
				}
            }      
		}
		
	}
	
	class MyOnItemClickListener implements ListView.OnItemClickListener {

		@Override
		public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
				long arg3) {
			if(arg1.getTag() != null) {
				
				Intent tint = new Intent(Intent.ACTION_VIEW,Uri.parse((String)arg1.getTag()));
				startActivity(tint);
			}
			
		}
		
	}
}
